﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using V2TEK.NET.SH.Silverlight.Charts.Core;
using V2TEK.NET.SH.Silverlight.Charts.TimeLineHelper;

namespace V2TEK.NET.SH.Silverlight.Charts
{
    /// <summary>
    /// 可以设置多行TimeLineLayout，每个TimeLineLayout的ContentWidth是一样的。
    /// 需要为不同的TimeLineLayout提供不同的DateTimeRangeDescriptor
    /// TimeLineLayout将根据不同的DateTimeRangeDescriptor计算不同的Column数据
    /// Viewer将根据不同的Column数据使用Renderer展示
    /// 本控件可脱离Gantt独立运行
    /// </summary>
    public class TimeLine : Core.Chart
    {
        private TimeLineViewer _viewer;
        private double _contentWidthOffSet;

        public static DependencyProperty ContentHeightProperty = DependencyProperty.Register("ContentHeight", typeof(double), typeof(TimeLine), new PropertyMetadata(20d));
        public static DependencyProperty ContentWidthProperty = DependencyProperty.Register("ContentWidth", typeof(double), typeof(TimeLine), new PropertyMetadata(5000d));
        public static DependencyProperty ViewPortHeightPerTimeLineProperty = DependencyProperty.Register("ViewPortHeightPerTimeLine", typeof(double), typeof(TimeLine), new PropertyMetadata(20d));
        public static DependencyProperty ViewPortWidthProperty = DependencyProperty.Register("ViewPortWidth", typeof(double), typeof(TimeLine), new PropertyMetadata(1000d));

        public static DependencyProperty XPositionProperty = DependencyProperty.Register("XPosition", typeof(double), typeof(TimeLine), new PropertyMetadata(0d));

        public static DependencyProperty StartDateProperty = DependencyProperty.Register("StartDate", typeof(DateTime), typeof(TimeLine), new PropertyMetadata(DateTime.Now));
        public static DependencyProperty EndDateProperty = DependencyProperty.Register("EndDate", typeof(DateTime), typeof(TimeLine), new PropertyMetadata(DateTime.Now.AddMonths(1)));

        public static DependencyProperty SummaryLayoutProperty = DependencyProperty.Register("SummaryLayout", typeof(TimeLineLayout), typeof(TimeLine), new PropertyMetadata(new TimeLineLayout()));
        public static DependencyProperty DetailLayoutProperty = DependencyProperty.Register("DetailLayout", typeof(TimeLineLayout), typeof(TimeLine), new PropertyMetadata(new TimeLineLayout()));

        public static readonly DependencyProperty MinDateTimeRangeWidthProperty = DependencyProperty.Register("MinDateTimeRangeWidth", typeof(double), typeof(TimeLine), new PropertyMetadata(60d));
 

        #region Public Property

        public DateTime StartDate
        {
            get { return (DateTime)GetValue(StartDateProperty); }
            set { SetValue(StartDateProperty, value); }
        }

        public DateTime EndDate
        {
            get { return (DateTime)GetValue(EndDateProperty); }
            set { SetValue(EndDateProperty, value); }
        }

        public double MinDateTimeRangeWidth
        {
            get
            {
                return (double)GetValue(MinDateTimeRangeWidthProperty);
            }
            set
            {
                SetValue(MinDateTimeRangeWidthProperty, value);
            }
        }

        public double ViewPortHeight
        {
            get
            {
                return 2d * ViewPortHeightPerTimeLine;
            }
        }

        public double ViewPortHeightPerTimeLine
        {
            get { return (double)GetValue(ViewPortHeightPerTimeLineProperty); }
            set { SetValue(ViewPortHeightPerTimeLineProperty, value); }
        }

        public double ViewPortWidth
        {
            get { return (double)GetValue(ViewPortWidthProperty); }
            set { SetValue(ViewPortWidthProperty, value); }
        }

        public double ContentHeight
        {
            get { return (double)GetValue(ContentHeightProperty); }
            set { SetValue(ContentHeightProperty, value); }
        }

        public double ContentWidth
        {
            get { return (double)GetValue(ContentWidthProperty); }
            set { SetValue(ContentWidthProperty, value); }
        }

        public double XPosition
        {
            get { return (double)GetValue(XPositionProperty); }
            set
            {
                SetValue(XPositionProperty, value);
            }
        }

        public double TotalMilliseconds
        {
            get
            {
                return EndDate.Subtract(StartDate).TotalMilliseconds;
            }
        }

        public double Zoom
        {
            get
            {
                return SummaryLayout.Zoom;
            }
        }

        public Dictionary<IDateTimeDescriptor, int> SummaryDateTimeDescriptors
        {
            get;
            set;
        }

        public Dictionary<IDateTimeDescriptor, int> DetailDateTimeDescriptors
        {
            get;
            set;
        }

        public Type ItemRendererProvider
        {
            get { return this.SummaryTimeLineViewer.ItemRendererProvider; }
            set 
            {
                this.DetailTimeLineViewer.ItemRendererProvider = this.SummaryTimeLineViewer.ItemRendererProvider = value;
            }
        }

        void Viewer_MouseMove(object sender, MouseEventArgs e)
        {
            
        }

        public TimeLineLayout SummaryLayout
        {
            get
            {
                return (TimeLineLayout)GetValue(SummaryLayoutProperty);
            }
            set
            {
                SetValue(SummaryLayoutProperty, value);
            }
        }

        public TimeLineLayout DetailLayout
        {
            get
            {
                return (TimeLineLayout)GetValue(DetailLayoutProperty);
            }
            set
            {
                SetValue(DetailLayoutProperty, value);
            }
        }

        protected TimeLineViewer SummaryTimeLineViewer
        {
            get;
            set;
        }

        protected TimeLineViewer DetailTimeLineViewer
        { get; set; }

        #endregion

        #region Constructs
        public TimeLine()
        {
            this.DefaultStyleKey = typeof(TimeLine);

            Binding bstart = new Binding("StartDate");
            bstart.Source = this;
            bstart.Mode = BindingMode.OneWay;
            this.SummaryLayout.SetBinding(TimeLineLayout.StartDateProperty, bstart);
            this.DetailLayout.SetBinding(TimeLineLayout.StartDateProperty, bstart);

            Binding bend = new Binding("EndDate");
            bend.Source = this;
            bend.Mode = BindingMode.OneWay;
            this.SummaryLayout.SetBinding(TimeLineLayout.EndDateProperty, bend);
            this.DetailLayout.SetBinding(TimeLineLayout.EndDateProperty, bend);

            Binding bch = new Binding("ContentHeight");
            bch.Source = this;
            bch.Mode = BindingMode.OneTime;
            this.SummaryLayout.SetBinding(TimeLineLayout.ContentHeightProperty, bch);
            this.DetailLayout.SetBinding(TimeLineLayout.ContentHeightProperty, bch);

            Binding bcw = new Binding("ContentWidth");
            bcw.Source = this;
            bcw.Mode = BindingMode.TwoWay;
            this.SummaryLayout.SetBinding(TimeLineLayout.ContentWidthProperty, bcw);
            this.DetailLayout.SetBinding(TimeLineLayout.ContentWidthProperty, bcw);

            Binding bvph = new Binding("ViewPortHeightPerTimeLine");
            bvph.Source = this;
            bvph.Mode = BindingMode.OneWay;
            this.SummaryLayout.SetBinding(TimeLineLayout.ViewPortHeightProperty, bvph);
            this.DetailLayout.SetBinding(TimeLineLayout.ViewPortHeightProperty, bvph);

            Binding bvpw = new Binding("ViewPortWidth");
            bvpw.Source = this;
            bvpw.Mode = BindingMode.OneWay;
            this.SummaryLayout.SetBinding(TimeLineLayout.ViewPortWidthProperty, bvpw);
            this.DetailLayout.SetBinding(TimeLineLayout.ViewPortWidthProperty, bvpw);

            Binding bx = new Binding("XPosition");
            bx.Source = this;
            bx.Mode = BindingMode.TwoWay;
            this.SummaryLayout.SetBinding(TimeLineLayout.XPositionProperty, bx);
            this.DetailLayout.SetBinding(TimeLineLayout.XPositionProperty, bx);

            Binding bmdtr = new Binding("MinDateTimeRangeWidth");
            bmdtr.Source = this;
            bmdtr.Mode = BindingMode.OneWay;
            this.SummaryLayout.SetBinding(TimeLineLayout.MinDateTimeRangeWidthProperty, bmdtr);
            this.DetailLayout.SetBinding(TimeLineLayout.MinDateTimeRangeWidthProperty, bmdtr);
        }
        #endregion

        public void Update()
        {
            SummaryLayout.Update();
            DetailLayout.Update();
        }

        # region override
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            //this.SummaryLayout = this.GetTemplateChild("SummaryLayout") as TimeLineLayout;
            //this.DetailLayout = this.GetTemplateChild("DetailLayout") as TimeLineLayout;
            if (this.SummaryDateTimeDescriptors == null)
                this.SummaryDateTimeDescriptors = DateTimeRangeDescriptorUtil.DefaultDateTimeRangeDescriptor2;

            this.SummaryLayout.DateTimeDescriptors = this.SummaryDateTimeDescriptors;
            if (this.DetailDateTimeDescriptors == null)
                this.DetailDateTimeDescriptors = DateTimeRangeDescriptorUtil.DefaultDateTimeRangeDescriptor;
            this.DetailLayout.DateTimeDescriptors = this.DetailDateTimeDescriptors;

            this.SummaryTimeLineViewer = this.GetTemplateChild("SummaryTimeLine") as TimeLineViewer;
            this.DetailTimeLineViewer = this.GetTemplateChild("DetailTimeLine") as TimeLineViewer;

            this.SummaryLayout.OnLayoutUpdate += new LayoutUpdate(this.SummaryTimeLineViewer.OnUpdate);
            this.DetailLayout.OnLayoutUpdate += new LayoutUpdate(this.DetailTimeLineViewer.OnUpdate);

            //this.Update();
        }

        /// <summary>
        /// 所有布局都是相对于父元素的。如果将原点设置为 0,0，会将子元素放置在父面板的左上角，而不是放置在 Silverlight 插件的左上角。
        /// </summary>
        /// <param name="finalSize"></param>
        /// <returns></returns>
        //protected override Size ArrangeOverride(Size finalSize)
        //{
        //    //固定TimeLine可视化窗口大小
        //    RectangleGeometry mask = new RectangleGeometry();
        //    mask.Rect = new Rect(0, 0, ViewPortWidth, ViewPortHeight);
        //    this.Clip = mask;
        //    return base.ArrangeOverride(finalSize);
        //}

        protected override Size MeasureOverride(Size availableSize)
        {
            if (this.SummaryTimeLineViewer.Layout == null)
                this.Update();

            Size size = new Size(ViewPortWidth, ViewPortHeightPerTimeLine);
            this.SummaryTimeLineViewer.Measure(size);
            this.DetailTimeLineViewer.Measure(size);
            return base.MeasureOverride(new Size(ViewPortWidth, ViewPortHeightPerTimeLine * 2));
        }

        #endregion     
    }
}
